package com.school.sports.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.school.sports.entity.*;
import com.school.sports.mapper.CertificateRecordMapper;
import com.school.sports.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 证书记录服务实现类
 */
@Service
public class CertificateRecordServiceImpl extends ServiceImpl<CertificateRecordMapper, CertificateRecord> implements CertificateRecordService {

    private static final Logger logger = LoggerFactory.getLogger(CertificateRecordServiceImpl.class);

    @Autowired
    private UserService userService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private AwardService awardService;

    @Autowired
    private CertificateTemplateService certificateTemplateService;

    @Autowired
    private FileInfoService fileInfoService;

    @Override
    public IPage<CertificateRecord> getPage(int currentPage, int pageSize, CertificateRecord record) {
        Page<CertificateRecord> page = new Page<>(currentPage, pageSize);
        return baseMapper.selectRecordPageWithUserName(page, record);
    }

    @Override
    @Transactional
    public CertificateRecord generateParticipationCertificate(Long userId, Long projectId, Long generateUserId) {
        try {
            // 验证参数
            User user = userService.getById(userId);
            if (user == null) {
                throw new IllegalArgumentException("用户不存在");
            }

            Project project = projectService.getById(projectId);
            if (project == null) {
                throw new IllegalArgumentException("项目不存在");
            }

            // 检查是否已经生成过参赛证书
            CertificateRecord existingRecord = getExistingCertificate(userId, projectId, null, "participation");
            if (existingRecord != null) {
                logger.info("用户已存在参赛证书，用户ID：{}，项目ID：{}", userId, projectId);
                return existingRecord;
            }

            // 获取参赛证书模板
            CertificateTemplate template = certificateTemplateService.getDefaultTemplateByType("participation");
            if (template == null) {
                throw new IllegalArgumentException("参赛证书模板不存在");
            }

            // 生成证书文件
            String certificateFileUrl = generateCertificateFile(user, project, null, null, template);

            // 创建证书记录
            CertificateRecord record = new CertificateRecord();
            record.setCertificateNo(generateCertificateNo());
            record.setCertificateType("participation");
            record.setRecipientUserId(userId);
            record.setRecipientName(user.getRealName());
            record.setRecipientDepartment(user.getClassName());
            record.setProjectId(projectId);
            record.setProjectName(project.getName());
            record.setCertificateTitle("参赛证书");
            record.setCertificateContent(generateParticipationContent(user, project));
            record.setIssueDate(LocalDateTime.now());
            record.setIssuingAuthority("校园运动会组委会");
            record.setCertificateFilePath(certificateFileUrl);
            record.setCertificateFileUrl(certificateFileUrl);
            record.setTemplateId(template.getId());
            record.setGenerateUserId(generateUserId);
            record.setStatus("normal");
            record.setCreatedAt(LocalDateTime.now());
            record.setUpdatedAt(LocalDateTime.now());

            save(record);
            logger.info("参赛证书生成成功，证书编号：{}", record.getCertificateNo());
            return record;

        } catch (Exception e) {
            logger.error("生成参赛证书失败：{}", e.getMessage(), e);
            throw new RuntimeException("生成参赛证书失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public CertificateRecord generateAwardCertificate(Long userId, Long projectId, Long awardId, String awardLevel, Long generateUserId) {
        try {
            // 验证参数
            User user = userService.getById(userId);
            if (user == null) {
                throw new IllegalArgumentException("用户不存在");
            }

            Project project = projectService.getById(projectId);
            if (project == null) {
                throw new IllegalArgumentException("项目不存在");
            }

            Award award = awardService.getById(awardId);
            if (award == null) {
                throw new IllegalArgumentException("奖项不存在");
            }

            // 检查是否已经生成过获奖证书
            CertificateRecord existingRecord = getExistingCertificate(userId, projectId, awardId, "award");
            if (existingRecord != null) {
                logger.info("用户已存在获奖证书，用户ID：{}，奖项ID：{}", userId, awardId);
                return existingRecord;
            }

            // 获取获奖证书模板
            CertificateTemplate template = certificateTemplateService.getDefaultTemplateByType("award");
            if (template == null) {
                throw new IllegalArgumentException("获奖证书模板不存在");
            }

            // 生成证书文件
            String certificateFileUrl = generateCertificateFile(user, project, award, awardLevel, template);

            // 创建证书记录
            CertificateRecord record = new CertificateRecord();
            record.setCertificateNo(generateCertificateNo());
            record.setCertificateType("award");
            record.setRecipientUserId(userId);
            record.setRecipientName(user.getRealName());
            record.setRecipientDepartment(user.getClassName());
            record.setProjectId(projectId);
            record.setProjectName(project.getName());
            record.setAwardId(awardId);
            record.setAwardLevel(awardLevel);
            record.setCertificateTitle("获奖证书");
            record.setCertificateContent(generateAwardContent(user, project, awardLevel));
            record.setIssueDate(LocalDateTime.now());
            record.setIssuingAuthority("校园运动会组委会");
            record.setCertificateFilePath(certificateFileUrl);
            record.setCertificateFileUrl(certificateFileUrl);
            record.setTemplateId(template.getId());
            record.setGenerateUserId(generateUserId);
            record.setStatus("normal");
            record.setCreatedAt(LocalDateTime.now());
            record.setUpdatedAt(LocalDateTime.now());

            save(record);
            logger.info("获奖证书生成成功，证书编号：{}", record.getCertificateNo());
            return record;

        } catch (Exception e) {
            logger.error("生成获奖证书失败：{}", e.getMessage(), e);
            throw new RuntimeException("生成获奖证书失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public CertificateRecord generateVolunteerCertificate(Long userId, Long generateUserId) {
        try {
            // 验证参数
            User user = userService.getById(userId);
            if (user == null) {
                throw new IllegalArgumentException("用户不存在");
            }

            // 检查是否已经生成过志愿者证书
            CertificateRecord existingRecord = getExistingCertificate(userId, null, null, "volunteer");
            if (existingRecord != null) {
                logger.info("用户已存在志愿者证书，用户ID：{}", userId);
                return existingRecord;
            }

            // 获取志愿者证书模板
            CertificateTemplate template = certificateTemplateService.getDefaultTemplateByType("volunteer");
            if (template == null) {
                throw new IllegalArgumentException("志愿者证书模板不存在");
            }

            // 生成证书文件
            String certificateFileUrl = generateCertificateFile(user, null, null, null, template);

            // 创建证书记录
            CertificateRecord record = new CertificateRecord();
            record.setCertificateNo(generateCertificateNo());
            record.setCertificateType("volunteer");
            record.setRecipientUserId(userId);
            record.setRecipientName(user.getRealName());
            record.setRecipientDepartment(user.getClassName());
            record.setCertificateTitle("志愿者证书");
            record.setCertificateContent(generateVolunteerContent(user));
            record.setIssueDate(LocalDateTime.now());
            record.setIssuingAuthority("校园运动会组委会");
            record.setCertificateFilePath(certificateFileUrl);
            record.setCertificateFileUrl(certificateFileUrl);
            record.setTemplateId(template.getId());
            record.setGenerateUserId(generateUserId);
            record.setStatus("normal");
            record.setCreatedAt(LocalDateTime.now());
            record.setUpdatedAt(LocalDateTime.now());

            save(record);
            logger.info("志愿者证书生成成功，证书编号：{}", record.getCertificateNo());
            return record;

        } catch (Exception e) {
            logger.error("生成志愿者证书失败：{}", e.getMessage(), e);
            throw new RuntimeException("生成志愿者证书失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public CertificateRecord generateRefereeCertificate(Long userId, Long generateUserId) {
        try {
            // 验证参数
            User user = userService.getById(userId);
            if (user == null) {
                throw new IllegalArgumentException("用户不存在");
            }

            // 检查是否已经生成过裁判证书
            CertificateRecord existingRecord = getExistingCertificate(userId, null, null, "referee");
            if (existingRecord != null) {
                logger.info("用户已存在裁判证书，用户ID：{}", userId);
                return existingRecord;
            }

            // 获取裁判证书模板
            CertificateTemplate template = certificateTemplateService.getDefaultTemplateByType("referee");
            if (template == null) {
                throw new IllegalArgumentException("裁判证书模板不存在");
            }

            // 生成证书文件
            String certificateFileUrl = generateCertificateFile(user, null, null, null, template);

            // 创建证书记录
            CertificateRecord record = new CertificateRecord();
            record.setCertificateNo(generateCertificateNo());
            record.setCertificateType("referee");
            record.setRecipientUserId(userId);
            record.setRecipientName(user.getRealName());
            record.setRecipientDepartment(user.getClassName());
            record.setCertificateTitle("裁判证书");
            record.setCertificateContent(generateRefereeContent(user));
            record.setIssueDate(LocalDateTime.now());
            record.setIssuingAuthority("校园运动会组委会");
            record.setCertificateFilePath(certificateFileUrl);
            record.setCertificateFileUrl(certificateFileUrl);
            record.setTemplateId(template.getId());
            record.setGenerateUserId(generateUserId);
            record.setStatus("normal");
            record.setCreatedAt(LocalDateTime.now());
            record.setUpdatedAt(LocalDateTime.now());

            save(record);
            logger.info("裁判证书生成成功，证书编号：{}", record.getCertificateNo());
            return record;

        } catch (Exception e) {
            logger.error("生成裁判证书失败：{}", e.getMessage(), e);
            throw new RuntimeException("生成裁判证书失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public List<CertificateRecord> batchGenerateCertificates(List<Long> userIds, String certificateType,
                                                          Long projectId, Long awardId, String awardLevel, Long generateUserId) {
        List<CertificateRecord> results = new ArrayList<>();

        for (Long userId : userIds) {
            try {
                CertificateRecord record = null;
                switch (certificateType) {
                    case "participation":
                        record = generateParticipationCertificate(userId, projectId, generateUserId);
                        break;
                    case "award":
                        record = generateAwardCertificate(userId, projectId, awardId, awardLevel, generateUserId);
                        break;
                    case "volunteer":
                        record = generateVolunteerCertificate(userId, generateUserId);
                        break;
                    case "referee":
                        record = generateRefereeCertificate(userId, generateUserId);
                        break;
                    default:
                        logger.warn("不支持的证书类型：{}", certificateType);
                        continue;
                }
                if (record != null) {
                    results.add(record);
                }
            } catch (Exception e) {
                logger.error("批量生成证书失败，用户ID：{}，错误：{}", userId, e.getMessage());
                // 继续处理其他用户
            }
        }

        return results;
    }

    @Override
    @Transactional
    public CertificateRecord regenerateCertificate(Long certificateId, Long generateUserId) {
        CertificateRecord existingRecord = getById(certificateId);
        if (existingRecord == null) {
            throw new IllegalArgumentException("证书不存在");
        }

        try {
            // 删除原有证书文件
            if (StringUtils.hasText(existingRecord.getCertificateFilePath())) {
                // 这里可以添加删除物理文件的逻辑
            }

            // 重新生成证书
            CertificateRecord newRecord = null;
            switch (existingRecord.getCertificateType()) {
                case "participation":
                    newRecord = generateParticipationCertificate(
                            existingRecord.getRecipientUserId(),
                            existingRecord.getProjectId(),
                            generateUserId
                    );
                    break;
                case "award":
                    newRecord = generateAwardCertificate(
                            existingRecord.getRecipientUserId(),
                            existingRecord.getProjectId(),
                            existingRecord.getAwardId(),
                            existingRecord.getAwardLevel(),
                            generateUserId
                    );
                    break;
                case "volunteer":
                    newRecord = generateVolunteerCertificate(
                            existingRecord.getRecipientUserId(),
                            generateUserId
                    );
                    break;
                case "referee":
                    newRecord = generateRefereeCertificate(
                            existingRecord.getRecipientUserId(),
                            generateUserId
                    );
                    break;
            }

            // 更新原证书记录状态
            existingRecord.setStatus("reissued");
            updateById(existingRecord);

            return newRecord;

        } catch (Exception e) {
            logger.error("重新生成证书失败：{}", e.getMessage(), e);
            throw new RuntimeException("重新生成证书失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public boolean revokeCertificate(Long certificateId) {
        CertificateRecord record = getById(certificateId);
        if (record == null) {
            return false;
        }

        record.setStatus("revoked");
        record.setUpdatedAt(LocalDateTime.now());
        boolean result = updateById(record);

        if (result) {
            logger.info("证书撤销成功，证书编号：{}", record.getCertificateNo());
        } else {
            logger.error("证书撤销失败，证书编号：{}", record.getCertificateNo());
        }

        return result;
    }

    @Override
    public List<CertificateRecord> getCertificatesByUserId(Long userId) {
        if (userId == null) {
            return new ArrayList<>();
        }
        return baseMapper.selectByRecipientUserId(userId);
    }

    @Override
    public List<CertificateRecord> getCertificatesByProjectId(Long projectId) {
        if (projectId == null) {
            return new ArrayList<>();
        }
        return baseMapper.selectByProjectId(projectId);
    }

    @Override
    public List<CertificateRecord> getCertificatesByAwardId(Long awardId) {
        if (awardId == null) {
            return new ArrayList<>();
        }
        return baseMapper.selectByAwardId(awardId);
    }

    @Override
    public CertificateRecord getCertificateByNo(String certificateNo) {
        if (!StringUtils.hasText(certificateNo)) {
            return null;
        }
        return baseMapper.selectByCertificateNo(certificateNo);
    }

    @Override
    public boolean validateCertificate(String certificateNo) {
        CertificateRecord record = getCertificateByNo(certificateNo);
        return record != null && "normal".equals(record.getStatus());
    }

    @Override
    public List<CertificateRecord> getCertificateStatistics() {
        return baseMapper.selectCertificateStatistics();
    }

    @Override
    public List<CertificateRecord> getCertificatesByDateRange(String startDate, String endDate) {
        if (!StringUtils.hasText(startDate) || !StringUtils.hasText(endDate)) {
            return new ArrayList<>();
        }
        return baseMapper.selectByDateRange(startDate, endDate);
    }

    // ========== 私有方法 ==========

    /**
     * 生成证书编号
     */
    private String generateCertificateNo() {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String random = UUID.randomUUID().toString().substring(0, 8).toUpperCase();
        return "CERT" + timestamp + random;
    }

    /**
     * 检查是否已存在证书
     */
    private CertificateRecord getExistingCertificate(Long userId, Long projectId, Long awardId, String certificateType) {
        LambdaQueryWrapper<CertificateRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CertificateRecord::getRecipientUserId, userId)
               .eq(CertificateRecord::getCertificateType, certificateType)
               .eq(CertificateRecord::getStatus, "normal");

        if (projectId != null) {
            wrapper.eq(CertificateRecord::getProjectId, projectId);
        }
        if (awardId != null) {
            wrapper.eq(CertificateRecord::getAwardId, awardId);
        }

        return getOne(wrapper);
    }

    /**
     * 生成证书文件（简化实现，实际应该根据模板生成PDF或图片）
     */
    private String generateCertificateFile(User user, Project project, Award award, String awardLevel, CertificateTemplate template) {
        // 这里是简化实现，实际应该使用模板引擎生成PDF或图片
        String fileName = "certificate_" + user.getId() + "_" + System.currentTimeMillis() + ".pdf";
        return "/api/certificate/download/" + fileName;
    }

    /**
     * 生成参赛证书内容
     */
    private String generateParticipationContent(User user, Project project) {
        return String.format("兹证明 %s 同学参加我校运动会 %s 项目，表现优异，特发此证，以资鼓励。",
                user.getRealName(), project.getName());
    }

    /**
     * 生成获奖证书内容
     */
    private String generateAwardContent(User user, Project project, String awardLevel) {
        return String.format("兹证明 %s 同学在我校运动会 %s 项目中荣获 %s，特发此证，以资鼓励。",
                user.getRealName(), project.getName(), awardLevel);
    }

    /**
     * 生成志愿者证书内容
     */
    private String generateVolunteerContent(User user) {
        return String.format("兹证明 %s 同学在我校运动会期间担任志愿者工作，表现突出，特发此证，以资鼓励。",
                user.getRealName());
    }

    /**
     * 生成裁判证书内容
     */
    private String generateRefereeContent(User user) {
        return String.format("兹证明 %s 老师在我校运动会期间担任裁判工作，表现突出，特发此证，以资鼓励。",
                user.getRealName());
    }
}